package com.yiyi.user.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePayModel;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.nativepay.model.Transaction;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import com.yiyi.common.core.controller.BaseController;
import com.yiyi.common.core.domain.AjaxResult;
import com.yiyi.system.domain.ConversionType;
import com.yiyi.user.component.AliPayTemplate;
import com.yiyi.user.config.AlipayConfig;
import com.yiyi.user.config.WeiXinConfig;
import com.yiyi.user.domain.CustomerInfo;
import com.yiyi.user.domain.OrderInfo;
import com.yiyi.user.domain.SysPrice;
import com.yiyi.user.mhUtils.PayUtils;
import com.yiyi.user.model.AliPayModel;
import com.yiyi.user.service.ICustomerInfoService;
import com.yiyi.user.service.IOrderInfoService;
import com.yiyi.user.service.ISysPriceService;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@RestController
@RequestMapping("/customer/wxPay")
public class wxPayController extends BaseController {

    @Autowired
    private IOrderInfoService orderInfoService;

    @Autowired
    private ICustomerInfoService customerInfoService;

    @Autowired
    private ISysPriceService sysPriceService;

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());


    @Autowired
    private AlipayConfig alipayProperties;

    /**
     * jsapi支付
     */
    @Autowired
    private JsapiService jsapiService;
    @Autowired
    private WeiXinConfig weiXinConfig;

    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private AliPayTemplate aliPayTemplate;

    /**
     * （点击测算按钮）预支付-保存客户信息
     */
    @PostMapping("/yuPayWxPay")
    public AjaxResult yuPayWxPay(@RequestBody CustomerInfo customerInfo) {
        // 系统逻辑
        // 保存客户信息
        customerInfoService.insertCustomerInfo(customerInfo);
        return success(customerInfo);
    }

    /**
     * 获取支付金额
     */
    public BigDecimal getPrice(){
        // 获取支付金额
        List<SysPrice> sysPrices = sysPriceService.selectSysPriceList(null);

        //TODO 正式必须修改
       // return BigDecimal.valueOf(0.01);
        return sysPrices.get(0).getPrice();
    }

    /**
     * 下单逻辑
     * @param orderNum  订单编号
     * @param customerId  客户id
     * @param domainUrl  域名地址
     * @param description  描述
     * @return
     */
    public int createOrder(String orderNum, Long customerId, String domainUrl, String description, int payType){
        // 1、创建订单
        OrderInfo orderInfo = new OrderInfo();
        // 订单编号
        orderInfo.setOrderNumber(orderNum);
        // 0未支付，1已支付，2：已取消
        orderInfo.setPayStatus("0");
        // 设置用户id
        orderInfo.setCustomerId(customerId);
        // 获取支付金额
        orderInfo.setPayAmount(getPrice());
        // 获取域名地址
        orderInfo.setDomainUrl(domainUrl);
        // 获取订单描述（姓名+功能（如：张三的八字测算））
        orderInfo.setDescription(description);
        // 支付类型（0：支付宝，1：微信）
        orderInfo.setPayType(payType);
        // 创建时间
        orderInfo.setCreateTime(new Date());
        return orderInfoService.insertOrderInfo(orderInfo);
    }

    /**
     * 判断当前订单是否 存在
     * true 正常
     * false 异常 -订单存在
     * @param orderNum
     * @return
     */
    public boolean isOrder(String orderNum){
        // 判断当前订单是否 存在
        // 1、创建订单
        OrderInfo orderInfo = new OrderInfo();
        // 订单编号
        orderInfo.setOrderNumber(orderNum);
        if (orderInfoService.getOrderDataByOrderNum(orderInfo) == null){
            return true;
        }else {
            // 存在 报错
            return false;
        }
    }


    /**
     * 判断是否付款
     */
    public boolean isPay(String orderNum){
        // 判断当前订单是否 存在
        // 1、创建订单
        OrderInfo orderInfo = new OrderInfo();
        // 订单编号
        orderInfo.setOrderNumber(orderNum);
        if (orderInfoService.isPay(orderInfo) == null){
            return true;
        }else {
            // 存在 报错
            return false;
        }
    }

    /**
     * 修改订单状态 -已支付 逻辑
     * @param orderNum  订单编号
     */
    public void updateOrder(String orderNum){
        OrderInfo orderInfo = new OrderInfo();
        // 已支付
        orderInfo.setPayStatus("1");
        orderInfo.setOrderNumber(orderNum);
        orderInfo.setPatTime(new Date());
        orderInfoService.notify(orderInfo);
    }

    /**
     * 微信支付（native）下单 并生成二维码地址
     */
    @PostMapping("/createPayWxPay")
    public AjaxResult createPayWxPay(@RequestBody OrderInfo orderInfo) {
        // 验证订单是否存在，以前有
        if (isPay(orderInfo.getOrderNumber()) == false){
            return success("201");
        }

        // 系统逻辑-下单 【支付类型（0：支付宝，1：微信）】
        createOrder(orderInfo.getOrderNumber()
                ,orderInfo.getCustomerId(),
                orderInfo.getDomainUrl(),
                orderInfo.getDescription(),1);

        Config config =new RSAAutoCertificateConfig.Builder()
                .merchantId(weiXinConfig.merchantId)
                .privateKeyFromPath(weiXinConfig.privateKeyPath)
                .merchantSerialNumber(weiXinConfig.merchantSerialNumber)
                .apiV3Key(weiXinConfig.apiV3Key)
                .build();
        NativePayService service = new NativePayService.Builder().config(config).build();
        // request.setXxx(val)设置所需参数，具体参数可见Request定义
        PrepayRequest request = new PrepayRequest();
        // 获取支付金额
        BigDecimal price = getPrice();

        Amount amount = new Amount();
        BigDecimal result = price.multiply(BigDecimal.valueOf(100));
        amount.setTotal(result.intValue()); // 商品价格
        request.setAmount(amount);
        request.setAppid(weiXinConfig.appId); // APPID
        request.setMchid(weiXinConfig.merchantId); // 商户号
        request.setDescription("测算支付"); // 商品名称
        request.setNotifyUrl(weiXinConfig.notifyDomain); // 回调地址
        request.setOutTradeNo(orderInfo.getOrderNumber()); // 你所生成的订单号
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
        // 微信二维码失效时间 4 分钟
        Date date = new Date(new Date().getTime() + 4 * 60 * 1000);
        String expire = format.format(date);
        request.setTimeExpire(expire);
        // 调用下单方法，得到应答
        PrepayResponse response = null;
        try {
            response = service.prepay(request);
        } catch (Exception e) {
            return warn("订单已支付！");
        }
        // 生成二维码链接
        String codeUrl = response.getCodeUrl();
        logger.info(codeUrl);
        return success(codeUrl);
    }

    /**
     * 微信支付异步通知
     */
    @RequestMapping("/wxpayNotify")
    public void notifyNative(HttpServletRequest request, HttpServletResponse response) throws IOException {

        // 获取请求体原内容（此时获取的数据是加密的）
        BufferedReader reader = request.getReader();
        StringBuilder requestBody = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            requestBody.append(line);
        }

        // 获取请求携带的数据，构造参数
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(request.getHeader("Wechatpay-Serial")) // 微信支付平台证书的序列号
                .nonce(request.getHeader("Wechatpay-Nonce")) // 签名中的随机数
                .signature(request.getHeader("Wechatpay-Signature"))  // 应答的微信支付签名
                .timestamp(request.getHeader("Wechatpay-Timestamp")) // 签名中的时间戳
                .body(requestBody.toString()) // 请求体内容（原始内容，不要解析）
                .build();

        //获取微信证书，没有的话重新构造一个
        Config config =new RSAAutoCertificateConfig.Builder()
                .merchantId(weiXinConfig.merchantId)
                .privateKeyFromPath(weiXinConfig.privateKeyPath)
                .merchantSerialNumber(weiXinConfig.merchantSerialNumber)
                .apiV3Key(weiXinConfig.apiV3Key)
                .build();

        NotificationParser parser = new NotificationParser((NotificationConfig) config);
        // 以支付通知回调为例，验签、解密并转换成 Transaction
        Transaction transaction = parser.parse(requestParam, Transaction.class);
        // 获取支付单号
        logger.info("支付成功，回调信息：{}", transaction);
        // 打印其中的"微信支付单号"字段，可用于查单操作
        logger.info("微信支付单号：{}", transaction.getTransactionId());
        logger.info("订单编号：{}", transaction.getOutTradeNo());
        // 获取微信支付回调状态
        Transaction.TradeStateEnum tradeState = transaction.getTradeState();
        logger.info("微信Native支付回调状态 tradeState:{}", tradeState);

        // 系统逻辑 修改订单状态- 已支付
        updateOrder(transaction.getOutTradeNo());
    }


    /**
     * 米花-手机小程序 微信支付 下单
     */
    @RequestMapping("/mhWeChatPayOrder")
    public AjaxResult mhWeChatPayOrder(@RequestBody OrderInfo orderInfo) {
        // 验证订单是否存在
        if (isOrder(orderInfo.getOrderNumber()) == false){
            return success("201");
        }

        // 系统逻辑-下单 【支付类型（0：支付宝，1：微信）】
        createOrder(orderInfo.getOrderNumber()
                ,orderInfo.getCustomerId(),
                orderInfo.getDomainUrl(),
                orderInfo.getDescription(),1);

        String merAccount = "6998106d4a21475a9a05d27460d7e571"; // 商户标识
        String merKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALLLDCKXR6AcfkLZWCxRfdUw+X6ErT175V78a8RDLDb12MBimhvuMUgxCWOsGjncA/ZvinthwqCyCcE4XcWKKjhh3pTsXHuVZkqBOHFmO6reMP5Xh1g8rcBc4OOihm70VmSwU6mYSROU1aV3hjd5pqYqCYwKvzeO0kChF1ZjuFjhAgMBAAECgYBX7tUBDjYD4P+YERz0bv/cIkISn140pwKgPLUjyYWtYixAMj5pDjTetH9RrgsX+cVZJnKNS/9U2TtC9F3qEZHBZlcf0aF0U+R8KFlIi/EBpMCnZ6qpMsvpfe/QN3A5u+TiPz5vTUy2HqBveDszOtuESedMLFmiLopFdqQYBsluIQJBAOKSqiuD7Gl+xLzLdg/brPsmkQE6q9Yaq/Yc/isfDdr/NWxWRcRJnX9YF5qNIybMJlxog7Yt51RQ6rhjj3YPbBMCQQDKA8A9TzQTwMNcr7DkLrRTfLOLp/j8XBWHy5lqcDOy/VrSHzRVploZoclk7Qr/sMK7DAxN6dXZsw4aL+FGON27AkAmgKf8ZxnIv6stLiItBba6o04m+FJ1OukYFMs4hrlzCsWIWIzYk235Uv4H3I4prK2kLHqdfeV+1ZVdqkWZ2XsTAkAyAB2rzxfHr9Vq8n1o7PprE5lo/qlM5QnbM5SEWMMjETxSd7C/Zk40u+uaFGW9haWdIE1HV5I7sOrTpnguplKTAkAQnW6ejS09sbOZS3ZaFhH6oEwFXkpgDvxmbmwRTmqtFt9AimYsvpHs7OO29YA/koKvrrBR9UttwXx7hUebihVX\n";
        String merNo = "10006146";
        String orderId = orderInfo.getOrderNumber(); // 商户订单号
        long time = System.currentTimeMillis() / 1000; // 时间戳

        // 获取支付金额
        BigDecimal price =  getPrice();

        DecimalFormat df = new DecimalFormat("#"); // 格式化为整数
        String amount = df.format(price.multiply(BigDecimal.valueOf(100))); //支付金额
        String product = "八字测算"; //商品名称
        String productDesc = "测算"; // 商品描述
        String payWay = "WEIXIN";
        String payType = "H5_WEIXIN";
        String userIp = "127.0.0.1"; //用户IP地址
        String returnUrl = orderInfo.getReturnUrl();
        String notifyUrl = "http://cs.xuanlingwenhua.com:8080/customer/wxPay/mhWeChatNotify";
        com.alibaba.fastjson.JSONObject json = new com.alibaba.fastjson.JSONObject();
        json.put("merAccount", merAccount);
        json.put("merNo", merNo);
        json.put("orderId", orderId);
        json.put("time", time);
        json.put("amount", amount);
        json.put("product", product);
        json.put("productDesc", productDesc);
        json.put("payWay", payWay);
        json.put("payType", payType);
        json.put("userIp", userIp);
        json.put("returnUrl", returnUrl);
        json.put("notifyUrl", notifyUrl);
        String sign = PayUtils.buildSign(json, merKey);
        json.put("sign", sign);
        String data = "";
        try {
            data = PayUtils.buildDataPrivate(json, merKey);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        com.alibaba.fastjson.JSONObject result = PayUtils.httpPost("https://platform.mhxxkj.com/paygateway/mbpay/order/v1", merAccount, data);
        return success(result);
    }

    /**
     * 微信支付-手机aliNotify
     */
    @RequestMapping("/weChatPayOrder")
    public AjaxResult weChatPayOrder(@RequestBody OrderInfo orderInfo) {
        // 验证订单是否存在
        if (isPay(orderInfo.getOrderNumber()) == false){
            return success("201");
        }

        // 系统逻辑-下单 【支付类型（0：支付宝，1：微信）】
        createOrder(orderInfo.getOrderNumber()
                ,orderInfo.getCustomerId(),
                orderInfo.getDomainUrl(),
                orderInfo.getDescription(),1);

        com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();
        // 商品价格
        com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();
        List<SysPrice> sysPrices = sysPriceService.selectSysPriceList(new SysPrice());
        BigDecimal price = sysPrices.get(0).getPrice();
        BigDecimal result = price.multiply(BigDecimal.valueOf(100));
        amount.setTotal(result.intValue()); // 商品价格
        request.setAmount(amount); // 金额
        request.setAppid(weiXinConfig.appId); // appid
        request.setMchid(weiXinConfig.merchantId); // 商户id

        Payer payer = new Payer();
        payer.setOpenid(orderInfo.getOpenId()); // 用户授权的openid
        request.setPayer(payer);
        request.setDescription("cesuan"); // 描述
        request.setNotifyUrl(weiXinConfig.notifyDomain); // 回调地址
        request.setOutTradeNo(orderInfo.getOrderNumber());  // 订单编号
        com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse response =
                null;
        try {
            // 调用下单方法，得到应答
            response = jsapiService.prepay(request);
        } catch (Exception e) {
            return warn("订单已支付！");
        }
        return success(result);
    }


    /**
     * 米花 微信支付 回调
     */
    @RequestMapping("/mhWeChatNotify")
    public Map mhWeChatNotify(HttpServletRequest request, HttpServletResponse httpServletResponse) {
        try {
            String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyywwil0egHH5C2VgsUX3VMPl+hK09e+Ve/GvEQyw29djAYpob7jFIMQljrBo53AP2b4p7YcKgsgnBOF3Fiio4Yd6U7Fx7lWZKgThxZjuq3jD+V4dYPK3AXODjooZu9FZksFOpmEkTlNWld4Y3eaamKgmMCr83jtJAoRdWY7hY4QIDAQAB";
            String data = request.getParameter("data");
            //公钥解密
            com.alibaba.fastjson.JSONObject json = PayUtils.decryptDataPublic(data, publicKey);
            //公钥验签
            String signaa = json.getString("sign");
            json.remove("sign");
            String signbb = PayUtils.buildSign(json, publicKey);

            System.out.println("处理后的 JSON 内容: " + json.toJSONString());

            // 获取订单编号
            String out_trade_no =  json.get("orderId").toString();

            // 系统逻辑 修改订单状态- 已支付
            updateOrder(out_trade_no);

            if (signaa.equals(signbb)) {
                System.out.println("true");
            } else {
                System.out.println("false");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String,String> map = new HashMap<>();
        map.put("SUCCESS", "交易成功!");
        return map;
    }




    /**
     * 米花-手机支付-支付宝支付 下单
     */
    @RequestMapping("/mhAliPayOrder")
    public AjaxResult mhAliPayOrder(@RequestBody OrderInfo orderInfo) {
        // 验证订单是否存在
        if (isOrder(orderInfo.getOrderNumber()) == false){
            return success("201");
        }

        // 系统逻辑-下单 【支付类型（0：支付宝，1：微信）】
        createOrder(orderInfo.getOrderNumber()
                ,orderInfo.getCustomerId(),
                orderInfo.getDomainUrl(),
                orderInfo.getDescription(),0);


        String merAccount = "6998106d4a21475a9a05d27460d7e571"; // 商户标识
        String merKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALLLDCKXR6AcfkLZWCxRfdUw+X6ErT175V78a8RDLDb12MBimhvuMUgxCWOsGjncA/ZvinthwqCyCcE4XcWKKjhh3pTsXHuVZkqBOHFmO6reMP5Xh1g8rcBc4OOihm70VmSwU6mYSROU1aV3hjd5pqYqCYwKvzeO0kChF1ZjuFjhAgMBAAECgYBX7tUBDjYD4P+YERz0bv/cIkISn140pwKgPLUjyYWtYixAMj5pDjTetH9RrgsX+cVZJnKNS/9U2TtC9F3qEZHBZlcf0aF0U+R8KFlIi/EBpMCnZ6qpMsvpfe/QN3A5u+TiPz5vTUy2HqBveDszOtuESedMLFmiLopFdqQYBsluIQJBAOKSqiuD7Gl+xLzLdg/brPsmkQE6q9Yaq/Yc/isfDdr/NWxWRcRJnX9YF5qNIybMJlxog7Yt51RQ6rhjj3YPbBMCQQDKA8A9TzQTwMNcr7DkLrRTfLOLp/j8XBWHy5lqcDOy/VrSHzRVploZoclk7Qr/sMK7DAxN6dXZsw4aL+FGON27AkAmgKf8ZxnIv6stLiItBba6o04m+FJ1OukYFMs4hrlzCsWIWIzYk235Uv4H3I4prK2kLHqdfeV+1ZVdqkWZ2XsTAkAyAB2rzxfHr9Vq8n1o7PprE5lo/qlM5QnbM5SEWMMjETxSd7C/Zk40u+uaFGW9haWdIE1HV5I7sOrTpnguplKTAkAQnW6ejS09sbOZS3ZaFhH6oEwFXkpgDvxmbmwRTmqtFt9AimYsvpHs7OO29YA/koKvrrBR9UttwXx7hUebihVX\n";
        String merNo = "10006146";
        String orderId = orderInfo.getOrderNumber(); // 商户订单号
        long time = System.currentTimeMillis() / 1000; // 时间戳

        // 获取支付金额
        BigDecimal price =  getPrice();

        DecimalFormat df = new DecimalFormat("#"); // 格式化为整数
        String amount = df.format(price.multiply(BigDecimal.valueOf(100))); //支付金额
        String product = "八字测算"; //商品名称
        String productDesc = "测算"; // 商品描述
        String payWay = "ALIPAY";
        String payType = "ALIPAY_H5";
        String userIp = "127.0.0.1"; //用户IP地址
        String returnUrl = orderInfo.getReturnUrl();
        String notifyUrl = "http://cs.xuanlingwenhua.com:8080/customer/wxPay/mhWeChatNotify";
        com.alibaba.fastjson.JSONObject json = new com.alibaba.fastjson.JSONObject();
        json.put("merAccount", merAccount);
        json.put("merNo", merNo);
        json.put("orderId", orderId);
        json.put("time", time);
        json.put("amount", amount);
        json.put("product", product);
        json.put("productDesc", productDesc);
        json.put("payWay", payWay);
        json.put("payType", payType);
        json.put("userIp", userIp);
        json.put("returnUrl", returnUrl);
        json.put("notifyUrl", notifyUrl);
        String sign = PayUtils.buildSign(json, merKey);
        json.put("sign", sign);
        String data = "";
        try {
            data = PayUtils.buildDataPrivate(json, merKey);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        com.alibaba.fastjson.JSONObject result = PayUtils.httpPost("https://platform.mhxxkj.com/paygateway/mbpay/order/v1", merAccount, data);
        return success(result);
    }

    /**
     * 米花-电脑端支付-支付宝支付 下单
     */
    @RequestMapping("/mhAliWebPayOrder")
    public AjaxResult mhAliWebPayOrder(@RequestBody OrderInfo orderInfo) {
        // 验证订单是否存在
        if (isOrder(orderInfo.getOrderNumber()) == false){
            return success("201");
        }

        // 系统逻辑-下单 【支付类型（0：支付宝，1：微信）】
        createOrder(orderInfo.getOrderNumber()
                ,orderInfo.getCustomerId(),
                orderInfo.getDomainUrl(),
                orderInfo.getDescription(),0);


        String merAccount = "6998106d4a21475a9a05d27460d7e571"; // 商户标识
        String merKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALLLDCKXR6AcfkLZWCxRfdUw+X6ErT175V78a8RDLDb12MBimhvuMUgxCWOsGjncA/ZvinthwqCyCcE4XcWKKjhh3pTsXHuVZkqBOHFmO6reMP5Xh1g8rcBc4OOihm70VmSwU6mYSROU1aV3hjd5pqYqCYwKvzeO0kChF1ZjuFjhAgMBAAECgYBX7tUBDjYD4P+YERz0bv/cIkISn140pwKgPLUjyYWtYixAMj5pDjTetH9RrgsX+cVZJnKNS/9U2TtC9F3qEZHBZlcf0aF0U+R8KFlIi/EBpMCnZ6qpMsvpfe/QN3A5u+TiPz5vTUy2HqBveDszOtuESedMLFmiLopFdqQYBsluIQJBAOKSqiuD7Gl+xLzLdg/brPsmkQE6q9Yaq/Yc/isfDdr/NWxWRcRJnX9YF5qNIybMJlxog7Yt51RQ6rhjj3YPbBMCQQDKA8A9TzQTwMNcr7DkLrRTfLOLp/j8XBWHy5lqcDOy/VrSHzRVploZoclk7Qr/sMK7DAxN6dXZsw4aL+FGON27AkAmgKf8ZxnIv6stLiItBba6o04m+FJ1OukYFMs4hrlzCsWIWIzYk235Uv4H3I4prK2kLHqdfeV+1ZVdqkWZ2XsTAkAyAB2rzxfHr9Vq8n1o7PprE5lo/qlM5QnbM5SEWMMjETxSd7C/Zk40u+uaFGW9haWdIE1HV5I7sOrTpnguplKTAkAQnW6ejS09sbOZS3ZaFhH6oEwFXkpgDvxmbmwRTmqtFt9AimYsvpHs7OO29YA/koKvrrBR9UttwXx7hUebihVX\n";
        String merNo = "10006146";
        String orderId = orderInfo.getOrderNumber(); // 商户订单号
        long time = System.currentTimeMillis() / 1000; // 时间戳

        // 获取支付金额
        BigDecimal price =  getPrice();

        DecimalFormat df = new DecimalFormat("#"); // 格式化为整数
        String amount = df.format(price.multiply(BigDecimal.valueOf(100))); //支付金额
        String product = "八字测算"; //商品名称
        String productDesc = "测算"; // 商品描述
        String payWay = "ALIPAY";
        String payType = "SCANPAY_ALIPAY";
        String userIp = "127.0.0.1"; //用户IP地址
        String returnUrl = orderInfo.getReturnUrl();
        String notifyUrl = "http://cs.xuanlingwenhua.com:8080/customer/wxPay/mhWeChatNotify";
        com.alibaba.fastjson.JSONObject json = new com.alibaba.fastjson.JSONObject();
        json.put("merAccount", merAccount);
        json.put("merNo", merNo);
        json.put("orderId", orderId);
        json.put("time", time);
        json.put("amount", amount);
        json.put("product", product);
        json.put("productDesc", productDesc);
        json.put("payWay", payWay);
        json.put("payType", payType);
        json.put("userIp", userIp);
        json.put("returnUrl", returnUrl);
        json.put("notifyUrl", notifyUrl);
        String sign = PayUtils.buildSign(json, merKey);
        json.put("sign", sign);
        String data = "";
        try {
            data = PayUtils.buildDataPrivate(json, merKey);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        com.alibaba.fastjson.JSONObject result = PayUtils.httpPost("https://platform.mhxxkj.com/paygateway/mbpay/order/v1", merAccount, data);
        return success(result);
    }



    /***
     * 百度推广  ocpc
     */
    private static final Integer RETRY_TIMES = 3;
    private static final String BAIDU_OCPC_URL = "https://ocpc.baidu.com/ocpcapi/api/uploadConvertData";


    @RequestMapping("/ocpc")
    public AjaxResult ocpc(@RequestBody ConversionType conversionType){
        String token = conversionType.getToken();
        List<ConversionType> conversionTypes = new ArrayList<>();
        // 编辑一条转化数据
        ConversionType cv = new ConversionType();
        cv.setLogidUrl(conversionType.getLogidUrl()); // 设置落地页url
        cv.setConvertType(conversionType.getNewType()); // 设置转化类型
        cv.setNewType(conversionType.getNewType());  // 设置转化类型
        conversionTypes.add(cv);
        return success(sendConvertData(token, conversionTypes));
    }

    private static Boolean sendConvertData(String token, List<ConversionType> conversionTypeList) {

        JsonObject data = new JsonObject();
        // 设置API接口回传Token
        data.addProperty("token", token);
        // 设置API接口回传conversionTypes
        data.add("conversionTypes",
                new Gson().toJsonTree(conversionTypeList, new TypeToken<List<ConversionType>>() {}.getType()).getAsJsonArray());
        // 发送的完整请求数据
        // do some log
        System.out.println("req data: " + data.toString());
        // 向百度发送数据
        return sendWithRetry(data.toString());

    }

    private static boolean sendWithRetry(String msg) {
        // 发送请求
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(BAIDU_OCPC_URL);
        post.setHeader("Content-type", "application/json; charset=UTF-8");
        StringEntity entity = new StringEntity(msg, Charset.forName("UTF-8"));
        entity.setContentEncoding("UTF-8");
        post.setEntity(entity);
        // 添加失败重试
        int retry = RETRY_TIMES;
        for (int i = 0; i < retry; i++) {
            try {
                HttpResponse response = client.execute(post);
                // 检验状态码，如果成功接收数据
                int code = response.getStatusLine().getStatusCode();
                if (code == HttpStatus.SC_OK) {
                    String res = EntityUtils.toString(response.getEntity());
                    JsonObject returnData = new JsonParser().parse(res).getAsJsonObject();
                    // 打印返回结果
                    // do some log
                    System.out.println("retry times :" + i + ", res data: " + res);

                    int status = returnData.getAsJsonObject("header").get("status").getAsInt();
                    System.err.println("status == 0 代表回传数据成功，其余情况回传数据失败>>>>"+status);
                    // status为4，代表服务端异常，可添加重试
                    if ( status != 4) {
                        return status == 0; // status == 0 代表回传数据成功，其余情况回传数据失败
                    }
                }
            } catch (IOException e) {
                System.err.println("status == 0 代表回传数据失败>>>>");
            }
        }
        return false;
    }




    /**
     * 根据Code获取微信用户信息
     * 获取session_key openid等
     *
     * @param code
     * @return
     */
    @GetMapping("/userInfo")
    public AjaxResult getUserInfoUrl(@org.springframework.web.bind.annotation.RequestParam("code") String code) throws WxErrorException {
        AjaxResult ajax = AjaxResult.success();
        //拿着code请求
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
        //获取openid
        String openId = wxMpOAuth2AccessToken.getOpenId();
        System.err.println("openid:{}" + openId);

        //获取微信信息
        WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
        System.err.println("wxMpUser:{}" + JSON.toJSONString(wxMpUser));

        ajax.put("openId", openId);
        System.err.println(ajax);
        return ajax;
    }

    /**
     * jsApi支付 下单
     *
     * @param orderInfo
     * @return
     * @throws Exception
     */
    @RequestMapping("/jsApiPay")
    public AjaxResult jsApiPay(@RequestBody OrderInfo orderInfo) throws Exception {
        com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();
        // 商品价格
        com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();
        List<SysPrice> sysPrices = sysPriceService.selectSysPriceList(new SysPrice());
        BigDecimal price = sysPrices.get(0).getPrice();
        BigDecimal result = price.multiply(BigDecimal.valueOf(100));
        amount.setTotal(result.intValue()); // 商品价格
        request.setAmount(amount); // 金额
        request.setAppid(weiXinConfig.appId); // appid
        request.setMchid(weiXinConfig.merchantId); // 商户id

        Payer payer = new Payer();
        payer.setOpenid(orderInfo.getOpenId()); // 用户授权的openid
        request.setPayer(payer);
        request.setDescription("cesuan"); // 描述
        request.setNotifyUrl(weiXinConfig.jsApiNotifyDomain); // 回调地址
        request.setOutTradeNo(orderInfo.getOrderNumber());  // 订单编号
        com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse response =
                null;
        try {
            // 调用下单方法，得到应答
            response = jsapiService.prepay(request);
        } catch (Exception e) {
            return warn("订单已支付！");
        }

        logger.info("[开始]预支付信息-prepayId : {}", response.getPrepayId());
        String prepayId = response.getPrepayId();
        // 构建 - 相关参数
        String time = String.valueOf(System.currentTimeMillis() / 1000);
        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        String packageStr = StrUtil.format("prepay_id={}", prepayId);
        // 构建 - 签名信息
        ArrayList<String> list = new ArrayList<>();
        list.add(weiXinConfig.appId);
        list.add(time);
        list.add(nonceStr);
        list.add(packageStr);

        // 操作 - 签名
        String packageSign = weiXinConfig.signV3(WeiXinConfig.buildSignMessage(list).getBytes());

        // 构建 - 响应信息
        Map<String, String> map = new HashMap<>();
        map.put("wxAppId", weiXinConfig.appId);
        map.put("wxTimeStamp", time);
        map.put("wxNonceStr", nonceStr);
        map.put("wxPackage", packageStr);
        map.put("wxSignType", "RSA");
        map.put("wxPaySign", packageSign);
        logger.info("[结束]预支付信息-WxPayJsApiPreVO : {}", JSONUtil.toJsonStr(map));
        return success(map);
    }

    /**
     * jsApi支付异步通知
     * 包括通知中的app_id、out_trade_no、total_amount是否与请求中的一致，并根据trade_status进行后续业务处理。
     * https://docs.open.alipay.com/194/103296
     */
    @RequestMapping("/jsApiWxNotify")
    public AjaxResult notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("微信公众号支付异步消息");

        // 构建 - 微信支付回调通知body数据
        String body = weiXinConfig.getVerifyNotifyBody(request);
        // 需要通过证书序列号查找对应的证书，verifyNotify 中有验证证书的序列号
        String plainText = weiXinConfig.verifyNotify(body, weiXinConfig.apiV3Key);
        JSONObject data = JSONObject.parseObject(plainText);

        /** 系统逻辑*/
        String out_trade_no = (String) JSONUtil.parseObj(plainText).get("out_trade_no");

        // 系统逻辑 修改订单状态- 已支付
        updateOrder(out_trade_no);

        return success(out_trade_no);
    }

    /**
     * 支付宝支付-非PC
     */
    @RequestMapping("/aliPayOrder")
    public AjaxResult aliPayOrder(@RequestBody OrderInfo orderInfo) {
        // 验证订单是否存在
        if (isPay(orderInfo.getOrderNumber()) == false){
            return success("201");
        }

        // 系统逻辑-下单 【支付类型（0：支付宝，1：微信）】
        createOrder(orderInfo.getOrderNumber()
                ,orderInfo.getCustomerId(),
                orderInfo.getDomainUrl(),
                orderInfo.getDescription(),0);
        String orderId = orderInfo.getOrderNumber(); // 商户订单号
        long time = System.currentTimeMillis() / 1000; // 时间戳

        // 获取支付金额
        BigDecimal price =  getPrice();

        DecimalFormat df = new DecimalFormat("#"); // 格式化为整数
        String amount = df.format(price.multiply(BigDecimal.valueOf(100))); //支付金额

        String returnUrl = orderInfo.getReturnUrl();
        String notifyUrl = alipayProperties.notifyUrl;

        AliPayModel model=new AliPayModel();
        model.setOutTradeNo(orderId);// 商户订单号
        model.setTotalAmount(price.toString());// 商品价格
        model.setSubject(orderInfo.getDescription());// 商品标题
        model.setStoreId(orderInfo.getCustomerName());//组织或公司名
        model.setTimeoutExpress("5m");
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        model.setReturnUrl(returnUrl);
        model.setNotifyUrl(notifyUrl);
        String qrCode=null;
        try {
             qrCode  = aliPayTemplate.aliPay(model);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return success(qrCode);
    }


    /**
     * 支付宝PC支付
     */
    @RequestMapping("/aliWebPayOrder")
    public AjaxResult aliWebPayOrder(@RequestBody OrderInfo orderInfo) {
        // 验证订单是否存在
        if (isPay(orderInfo.getOrderNumber()) == false){
            return success("201");
        }

        // 系统逻辑-下单 【支付类型（0：支付宝，1：微信）】
        createOrder(orderInfo.getOrderNumber()
                ,orderInfo.getCustomerId(),
                orderInfo.getDomainUrl(),
                orderInfo.getDescription(),0);
        String orderId = orderInfo.getOrderNumber(); // 商户订单号
        long time = System.currentTimeMillis() / 1000; // 时间戳

        // 获取支付金额
        BigDecimal price =  getPrice();

        AlipayClient alipayClient = new DefaultAlipayClient(alipayProperties.getGatewayUrl(), alipayProperties.getAppId(),
                alipayProperties.getAppPrivateKey(),
                "json", "utf-8", alipayProperties.getAlipayPublicKey(), "RSA2");

        AlipayTradePayModel qrCodePayment = new AlipayTradePayModel();
        qrCodePayment.setOutTradeNo(orderId);
        qrCodePayment.setTotalAmount(price.toString());
        qrCodePayment.setSubject(alipayProperties.getSubject());

        AlipayTradePrecreateRequest precreateRequest = new AlipayTradePrecreateRequest();
        precreateRequest.setNotifyUrl(alipayProperties.notifyUrl);
        precreateRequest.setBizModel(qrCodePayment);

        String qrCode="";
        try {
            //使用支付二维码
            AlipayTradePrecreateResponse precreateResponse = alipayClient.execute(precreateRequest);
            if (precreateResponse.isSuccess()) {
                qrCode = precreateResponse.getQrCode(); // 返回二维码图片地址或字符串
            } else {
                // 处理错误
                throw new AlipayApiException("支付宝预创建订单失败");
            }

        }catch (Exception e){
            System.out.println("异常 " + e.getMessage());
        }

        return success(qrCode);
    }

    /**
     * 支付宝通知
     */
    @RequestMapping("/aliNotify")
    public Map aliNotify(HttpServletRequest request) {
        try {
             String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
            System.out.println("=========进入支付宝通知======= " + out_trade_no);
            // 系统逻辑 修改订单状态- 已支付
            updateOrder(out_trade_no);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String,String> map = new HashMap<>();
        map.put("SUCCESS", "交易成功!");
        return map;
    }
}

